package crmdna.api.endpoint.mail;

import static crmdna.common.AssertUtils.ensure;
import static crmdna.common.AssertUtils.ensureEqual;
import static crmdna.common.AssertUtils.ensureNotNull;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiMethod.HttpMethod;

import crmdna.common.api.APIResponse;
import crmdna.common.api.APIResponse.Status;
import crmdna.common.api.APIUtils;
import crmdna.common.api.RequestInfo;
import crmdna.mail.Mail;
import crmdna.mail.Mandrill;
import crmdna.mail.StopWatch;

@Api(name = "mail")
public class MailApi {

  @ApiMethod(path = "sendDummyEmail", httpMethod = HttpMethod.POST)
  public APIResponse sendDummyEmail(@Nullable @Named("client") String client,
      @Named("toEmailAddressess") Set<String> to, @Named("fromEmailAddress") String from,
      @Nullable @Named("subAccount") String subAccount, @Nullable @Named("tags") Set<String> tags,
      @Nullable @Named("showStackTrace") Boolean showStackTrace, HttpServletRequest req) {

    if (client == null)
      client = "isha";

    try {
      StopWatch sw = StopWatch.createStarted();

      // Mandrill.send(mandrillApiKey, to, "dummy subject", "dummy html body", from, subAccount,
      // tags,
      // true, true);

      return new APIResponse().status(Status.SUCCESS).message("Email sent")
          .processingTimeInMS(sw.milliSecondsElapsed());

    } catch (Exception ex) {
      return APIUtils.toAPIResponse(ex, showStackTrace, new RequestInfo().client(client).req(req));
    }
  }

  @ApiMethod(path = "sendMandrillEmail", httpMethod = HttpMethod.POST)
  public APIResponse sendMandrillEmail(@Nullable @Named("client") String client,
      @Named("fromEmailAddress") String from, @Named("subject") String subject,
      @Named("toEmailAddresses") List<String> toEmailAddresses,
      @Nullable @Named("mergeVarFirstNames") List<String> firstNames,
      @Nullable @Named("mergeVarLastNames") List<String> lastNames,
      @Nullable @Named("memberIds") List<Long> memberIds,
      @Nullable @Named("subaccount") String subaccount,
      @Nullable @Named("bulkEmailId") Long bulkEmailId,
      @Nullable @Named("doNotMultipleForSameAddress") Boolean doNotSendMultipleForSameAddress,
      @Named("messageBody") List<String> messageBody, @Nullable @Named("tags") Set<String> tags,
      @Nullable @Named("showStackTrace") Boolean showStackTrace, HttpServletRequest req) {

    if (client == null)
      client = "isha";

    if (doNotSendMultipleForSameAddress == null)
      doNotSendMultipleForSameAddress = true;

    try {
      StopWatch sw = StopWatch.createStarted();

      StringBuilder builder = new StringBuilder();
      if (messageBody != null) {
        if (!messageBody.isEmpty())
          for (String s : messageBody) {
            builder.append(s);
          }
      }

      ensureNotNull(toEmailAddresses, "toEmailAddresses is null");
      ensure(!toEmailAddresses.isEmpty(), "No to email address specified");

      Map<String, Map<String, String>> emailVsMergeVar = new HashMap<>();

      if ((firstNames != null) && !firstNames.isEmpty()) {
        ensureEqual(toEmailAddresses.size(), firstNames.size(), "Incorrect number of firstNames");

        for (int i = 0; i < toEmailAddresses.size(); i++) {
          Map<String, String> map = new HashMap<>();
          map.put("FNAME", firstNames.get(i));

          emailVsMergeVar.put(toEmailAddresses.get(i), map);
        }
      }

      if ((lastNames != null) && !lastNames.isEmpty()) {
        ensureEqual(toEmailAddresses.size(), lastNames.size(), "Incorrect number of lastNames");

        for (int i = 0; i < toEmailAddresses.size(); i++) {
          Map<String, String> map;
          if (emailVsMergeVar.containsKey(toEmailAddresses.get(i)))
            map = emailVsMergeVar.get(toEmailAddresses.get(i));
          else
            map = new HashMap<>();

          map.put("LNAME", lastNames.get(i));

          emailVsMergeVar.put(toEmailAddresses.get(i), map);
        }
      }

      Map<String, Long> emailVsMemberId = new HashMap<>();
      if ((memberIds != null) && !memberIds.isEmpty()) {
        ensureEqual(memberIds.size(), memberIds.size(), "Incorrect number of member ids");

        for (int i = 0; i < toEmailAddresses.size(); i++) {
          emailVsMemberId.put(toEmailAddresses.get(i), memberIds.get(i));
        }
      }


      int numEmails =
          Mail.sendMandrillEmail(client, new HashSet<String>(toEmailAddresses), emailVsMergeVar,
              emailVsMemberId, subject, builder.toString(), from, subaccount, tags, bulkEmailId,
              doNotSendMultipleForSameAddress);


      return new APIResponse().status(Status.SUCCESS).message("[" + numEmails + "] emails sent")
          .processingTimeInMS(sw.milliSecondsElapsed());

    } catch (Exception ex) {
      return APIUtils.toAPIResponse(ex, showStackTrace, new RequestInfo().client(client).req(req));
    }
  }


  @ApiMethod(path = "createSubaccount", httpMethod = HttpMethod.POST)
  public APIResponse createSubaccount(@Nullable @Named("client") String client,
      @Named("mandrillApiKey") String apiKey, @Named("subAccount") String subaccount,
      @Nullable @Named("showStackTrace") Boolean showStackTrace, HttpServletRequest req) {

    if (client == null)
      client = "isha";

    try {
      StopWatch sw = StopWatch.createStarted();

      subaccount = Mandrill.createSubaccount(apiKey, subaccount);

      return new APIResponse().status(Status.SUCCESS)
          .message("Sub account [" + subaccount + "] created")
          .processingTimeInMS(sw.milliSecondsElapsed());

    } catch (Exception ex) {
      return APIUtils.toAPIResponse(ex, showStackTrace, new RequestInfo().client(client).req(req));
    }
  }
}
